package main

import (
	"io"
	"log"
	"myPlugin/plugins"
	"net/http"
	"plugin"
	"sync"
)

var (
	engine *Engine
	fnExec func(plugins.IEngine, string) string
)

type Engine struct {
	mutex sync.Mutex
	vars  map[string]interface{}
}

func (e *Engine) Set(key string, val interface{}) {
	e.mutex.Lock()
	defer e.mutex.Unlock()
	e.vars[key] = val
}

func (e *Engine) Get(key string) interface{} {
	e.mutex.Lock()
	defer e.mutex.Unlock()
	return e.vars[key]
}

func (e *Engine) Del(key string) {
	e.mutex.Lock()
	defer e.mutex.Unlock()
	delete(e.vars, key)
}

func load(filename string) {
	if engine == nil {
		engine = &Engine{vars: make(map[string]interface{})}
	}
	p, err := plugin.Open(filename)
	if err != nil {
		log.Println("open plugin err:", err, filename)
		return
	}

	fn, err := p.Lookup("Exec")
	if err != nil {
		log.Println("not found symbol Exec", err)
		return
	}

	fnExec = fn.(func(plugins.IEngine, string) string)

	log.Println("loaded plugin successed! file=", filename)
}
func handleLoad(w http.ResponseWriter, req *http.Request) {
	req.ParseForm()
	names := req.Form["name"]
	if len(names) > 0 {
		load(names[0])
	} else {
		log.Println("filename error")
	}
	io.WriteString(w, "done")
}
func handleHello(w http.ResponseWriter, req *http.Request) {
	str := fnExec(engine, "test")
	io.WriteString(w, str)
}
func main() {
	load("phone.so")
	http.HandleFunc("/load", handleLoad)
	http.HandleFunc("/hello", handleHello)
	log.Fatal(http.ListenAndServe(":12345", nil))
}
